// brief
// 
// reads file, creates new files 



#include "main.h"
#include "patterns.cpp"
#include "sorts.h"

int theMaxValue;

int fdsPlus[100];
int fdsMinus[100];


int createTemporaries(int number){
    int result;
    int absForNumber = abs(number);
    char string[] = "temp",my_file[strlen(string)+3],string2[] = ".csv";
    if(absForNumber > theMaxValue)
    {
        for(int i = theMaxValue; i < absForNumber; i++)
        {
            sprintf(my_file,"%s%dp%s",string, i+1,string2);
            fdsPlus[i+1] = open(my_file, O_RDWR|O_CREAT , 0666);
            sprintf(my_file,"%s%dm%s",string, i+1,string2);
            fdsMinus[i+1] = open(my_file, O_RDWR|O_CREAT , 0666);
        }
        theMaxValue = absForNumber;
    }
    if (absForNumber==0)
    {
        printf("not valid");
        exit(3);
    }
    if (number>0) result =  fdsPlus[absForNumber];
    else          result = fdsMinus[absForNumber];
    return result;
    
}

void unlinkTmp(){
    char string[] = "./temp",my_file[strlen(string)+3],string2[] = ".csv";
    
    for(int i = 1; i <= theMaxValue; i++)
    {
        sprintf(my_file,"%s%dp%s", string, i,string2);
        unlink(my_file);
        sprintf(my_file,"%s%dm%s", string, i,string2);
        unlink(my_file);
    }
    
}

void newSliceFunction(char *pointer, int size){
    int i=0;
    int places=0;
    bool negativ;
    int sign;
    while (i < size ) {
        negativ = false;
        if(pointer[i+places]=='-') negativ = true;
        while ((pointer[i+places]!=',')&&(i+places<size))  places++; 
        //while ((pointer[i+places]!=',')&&(i+places<size-1))  places++; 
        if (negativ) sign = -1*places+1;
        else sign = places;
        if (sign==0) sign++;
        write(createTemporaries(sign), &pointer[i], sizeof(char)*places);
        write(createTemporaries(sign), ",", sizeof(char));
        i = i + places + 1;
        places = 0;
    }
    
}

void stepReading(int fd, int size){
    
    char *ptr;
    if( fd == -1) {
        printf("Failed to open input file!\n");
        exit(1);
    }
    
    ptr = (char *)mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
    if( ptr == MAP_FAILED ){
        printf("Mapping failed!\n");
        printf("%s", strerror( errno ));
        exit(2);
    }
    
    //sorry, fdIn, we don't need you any more
    close(fd);    
    
    //function to slice
    newSliceFunction(ptr, size);
    
    //good bye, ptr, we do not need you too('
    munmap((char *)ptr, size);
    
    
}




int main(int argc, char *argv[])
{
    
   
    int fdOut;
    char *fileName;
    char inFile[] = "in.csv";
    
    if (argc>1) fileName = argv[1];
    else        fileName = inFile;
    theMaxValue = 0;
    
    Logger::Instance().msg(1, "start slicing the file");

    Iterator *iter = new Iterator(fileName);
    
    do stepReading(iter->next(),iter->numberToRead); while (iter->haveNext()) ;
    unlink("out.csv");
    fdOut = open("out.csv", O_RDWR|O_CREAT, 0666);
    
    Chooser *chs = new Chooser();
    int i = 1;
    chs->decideWhoWouldBeBetter(i);
    
    
    for (int i = -theMaxValue; i <= theMaxValue; i++) 
    {
        char *buf;
        if(i==0) i++;
        int size = (int)lseek(createTemporaries(i), 0, SEEK_END);
        buf = (char *)mmap(NULL, size, PROT_WRITE | PROT_READ| PROT_EXEC, MAP_SHARED, createTemporaries(i), 0);
        Logger::Instance().msg(1, "sorting");
        if( size != 0 ) chs->makeYourJob(i);
        close(createTemporaries(i));
        write(fdOut, buf, size);
        munmap((char *)buf, size);
        
        
    } 
    

    
    unlinkTmp();

    Logger::Instance().msg(1, "end");

  
    
    return 0;
} 